import { DrawInteractor } from "./drawInteractor";
import BezierCurveNodeGraph from "../shape/bezierCurve";
import { Point } from "@/shape/dependencies";
import { getScale } from "@/graphviewState";
export class BezierCurveDrawInteractor extends DrawInteractor {
  points: { x: number; y: number }[] = [];
  movePoint: { x: number; y: number } = { x: 0, y: 0 };
  drawing: boolean = false;
  ctx: CanvasRenderingContext2D | null;
  borderColor = "rgb(64,158,255)";
  isLeftKeyDown = false;
  preControlPoint = { x: 0, y: 0 };
  currentPositionPoint = { x: 0, y: 0 };
  nextControlPoint = { x: 0, y: 0 };
  // 用于区分鼠标双击和鼠标按下抬起
  mouseDownTime = 0;
  mouseUpTime = 0;
  interval = 200;
  constructor(target: HTMLCanvasElement) {
    super(target);
    this.ctx = this.target.getContext("2d");
  }
  handleMouseDown(e: MouseEvent) {
    // 防止双击时执行两次
    const time = Date.now();
    const interval = time - this.mouseDownTime;
    if (interval < this.interval) {
      return;
    }
    this.mouseDownTime = time;
    this.drawing = true;
    this.isLeftKeyDown = true;
    // 鼠标左键按下,记录当前的位置点
    this.currentPositionPoint.x = e.offsetX;
    this.currentPositionPoint.y = e.offsetY;
  }
  handleMouseUp(e: MouseEvent) {
    // 防止双击时执行两次
    const time = Date.now();
    const interval = time - this.mouseUpTime;
    if (interval < this.interval) {
      return;
    }
    this.mouseUpTime = time;
    this.isLeftKeyDown = false;
    const point = { x: e.offsetX, y: e.offsetY };
    if (this.points.length === 0) {
      // 贝塞尔曲线的第一个点,控制点和起始点相同
      // 添加位置点
      this.points.push(point);
      // 添加控制点
      this.points.push(point);
    } else {
      // 位置点前的控制点
      this.points.push({ ...this.preControlPoint });
      // 位置点
      this.points.push({ ...this.currentPositionPoint });
      // 位置点后的控制点
      this.points.push({ ...this.nextControlPoint });
    }
  }
  handleDoubleClick() {
    this.drawing = false;
    this.drawEnd();
  }
  handleMouseMove(e: MouseEvent) {
    if (!this.drawing) {
      return;
    }
    this.movePoint.x = e.offsetX;
    this.movePoint.y = e.offsetY;
    if (this.isLeftKeyDown) {
      // 左键按下时可以调整控制点
      this.nextControlPoint.x = e.offsetX;
      this.nextControlPoint.y = e.offsetY;
      this.preControlPoint.x = 2 * this.currentPositionPoint.x - e.offsetX;
      this.preControlPoint.y = 2 * this.currentPositionPoint.y - e.offsetY;
    } else {
      // 左键不按下,控制点默认为当前的鼠标位置
      this.nextControlPoint.x = e.offsetX;
      this.nextControlPoint.y = e.offsetY;
      this.preControlPoint.x = e.offsetX;
      this.preControlPoint.y = e.offsetY;
    }
    this.reDraw();
  }
  reDraw() {
    if (this.ctx) {
      this.emit("redraw");
      this.draw();
    }
  }
  draw() {
    if (!this.ctx) {
      return;
    }
    if (this.points.length === 0) {
      return;
    }
    if (this.isLeftKeyDown) {
      // 左键按下时的绘制
      this.handleLeftKeyDownDraw();
      return;
    }
    // 正常情况下的绘制
    const startPoint = this.points[0];
    this.ctx.restore();
    this.ctx.strokeStyle = this.borderColor;
    this.ctx.beginPath();
    this.ctx.moveTo(startPoint.x, startPoint.y);
    // this.points的最后一位是一个无效的控制点
    for (let i = 1; i < this.points.length - 1; i += 3) {
      const cpoint1 = this.points[i];
      const cpoint2 = this.points[i + 1];
      const point = this.points[i + 2];
      this.ctx.bezierCurveTo(
        cpoint1.x,
        cpoint1.y,
        cpoint2.x,
        cpoint2.y,
        point.x,
        point.y
      );
    }
    // 如果继续绘制,则最后一位可以当做前一位位置点的后控制点
    const cp1 = this.points[this.points.length - 1];
    // 默认前控制点和当前位置点在同一位置,可以通过鼠标移动来更改控制点位置
    const cp2 = { x: this.movePoint.x, y: this.movePoint.y };
    this.ctx.bezierCurveTo(
      cp1.x,
      cp1.y,
      cp2.x,
      cp2.y,
      this.movePoint.x,
      this.movePoint.y
    );
    this.ctx.stroke();
  }
  handleLeftKeyDownDraw() {
    if (!this.ctx) {
      return;
    }
    const points = [...this.points];
    points.push({ ...this.preControlPoint });
    points.push({ ...this.currentPositionPoint });
    const startPoint = points[0];
    this.ctx.strokeStyle = this.borderColor;
    this.ctx.beginPath();
    this.ctx.moveTo(startPoint.x, startPoint.y);
    for (let i = 1; i < points.length; i += 3) {
      const cpoint1 = points[i];
      const cpoint2 = points[i + 1];
      const point = points[i + 2];
      this.ctx.bezierCurveTo(
        cpoint1.x,
        cpoint1.y,
        cpoint2.x,
        cpoint2.y,
        point.x,
        point.y
      );
    }
    this.drawControlPoint();
  }
  drawControlPoint() {
    if (!this.ctx) {
      return;
    }
    this.ctx.save();
    this.ctx.fillStyle = "rgb(64,158,255)";
    // 后控制点
    this.ctx.moveTo(this.currentPositionPoint.x, this.currentPositionPoint.y);
    this.ctx.lineTo(this.nextControlPoint.x, this.nextControlPoint.y);
    this.ctx.fillRect(
      this.nextControlPoint.x - 3,
      this.nextControlPoint.y - 3,
      6,
      6
    );
    // 前控制点
    this.ctx.moveTo(this.currentPositionPoint.x, this.currentPositionPoint.y);
    this.ctx.lineTo(this.preControlPoint.x, this.preControlPoint.y);
    this.ctx.fillRect(
      this.preControlPoint.x - 3,
      this.preControlPoint.y - 3,
      6,
      6
    );
    this.ctx.stroke();
    this.ctx.restore();
  }
  drawEnd() {
    if (this.points.length <= 1) {
      // 只是在原点点击了一下,不会进行绘制
      return;
    }
    // 去除缩放对鼠标获取点坐标的影响
    const scale = getScale();
    const bezier = new BezierCurveNodeGraph();
    bezier.points = this.points.map((point) => {
      return new Point(point.x / scale, point.y / scale);
    });
    bezier.points.pop();
    bezier.saveOriginPoints();
    this.emit("drawend", bezier);
  }
}
